﻿using System;
using System.Collections.Generic;
using Runtime.Services.Battle;

namespace Runtime.Models {

    /// <summary>
    /// 单元格数据集
    /// </summary>
    public interface IDFR_ReadOnlyBattleCellDictionaryModelTD : IDFR_ReadOnlyDictionaryModel<DFR_BattleCellIndex, IDFR_BattleCellModelTD> {

        new IDFR_BattleCellDictionaryModelTD AsReadWrite();

        IDFR_ReadOnlyBattleCellDictionaryModelBase AsBase();
    }

    /// <summary>
    /// 单元格数据集
    /// </summary>
    public interface IDFR_BattleCellDictionaryModelTD : IDFR_ReadOnlyBattleCellDictionaryModelTD, IDFR_DictionaryModel<DFR_BattleCellIndex, IDFR_BattleCellModelTD> {

        new IDFR_BattleCellDictionaryModelBase AsBase();
    }

    [Implement(typeof(IDFR_ReadOnlyBattleCellDictionaryModelTD))]
    [Implement(typeof(IDFR_ReadOnlyBattleCellDictionaryModelBase))]
    [Implement(typeof(IDFR_ReadOnlyDictionaryModel<DFR_BattleCellIndex, IDFR_BattleCellModelTD>))]
    [Implement(typeof(IDFR_ReadOnlyDictionaryModel<DFR_BattleCellIndex, IDFR_BattleCellModelBase>))]
    [Implement(typeof(IDFR_BattleCellDictionaryModelTD))]
    [Implement(typeof(IDFR_BattleCellDictionaryModelBase))]
    [Implement(typeof(IDFR_DictionaryModel<DFR_BattleCellIndex, IDFR_BattleCellModelTD>))]
    [Implement(typeof(IDFR_DictionaryModel<DFR_BattleCellIndex, IDFR_BattleCellModelBase>))]
    internal sealed class DFR_BattleCellDictionaryModelTD : DFR_DictionaryModel<DFR_BattleCellIndex, IDFR_BattleCellModelTD>,
        IDFR_ReadOnlyBattleCellDictionaryModelTD, IDFR_BattleCellDictionaryModelTD,
        IDFR_ReadOnlyBattleCellDictionaryModelBase, IDFR_BattleCellDictionaryModelBase {

        public new IDFR_BattleCellDictionaryModelTD AsReadWrite() => this;
        IDFR_BattleCellDictionaryModelBase IDFR_ReadOnlyBattleCellDictionaryModelBase.AsReadWrite() => this;
        IDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase> IReadOnlyDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.AsReadWrite() => this;
        IReadOnlyDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase> IDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.AsReadOnly() => this;
        public IDFR_ReadOnlyBattleCellDictionaryModelBase AsBase() => this;
        IDFR_BattleCellDictionaryModelBase IDFR_BattleCellDictionaryModelTD.AsBase() => this;

        public DFR_BattleCellDictionaryModelTD() : base() {
            Updated += (key, oldValue, newValue) => m_Updated?.Invoke(key, oldValue, newValue);
            Added += (key, value) => m_Added?.Invoke(key, value);
            Removed += (key, value) => m_Removed?.Invoke(key, value);
            Cleared += () => m_Cleared?.Invoke();
        }

        protected override void Dispose() {
            m_Updated = null;
            m_Added = null;
            m_Removed = null;
            m_Cleared = null;
            base.Dispose();
        }

        IDFR_BattleCellModelBase IReadOnlyDictionary<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.this[DFR_BattleCellIndex key] => base[key];

        IEnumerable<DFR_BattleCellIndex> IReadOnlyDictionary<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Keys => Keys;

        IEnumerable<IDFR_BattleCellModelBase> IReadOnlyDictionary<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Values => Values;

        ICollection<IDFR_BattleCellModelBase> IDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Values => throw new NotImplementedException("由于ICollection 存在可写，不可逆变，使用只读相关接口完成逆变");

        ICollection<IDFR_BattleCellModelBase> IDictionary<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Values => throw new NotImplementedException("由于ICollection 存在可写，不可逆变，使用只读相关接口完成逆变");

        IDFR_BattleCellModelBase IDictionary<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.this[DFR_BattleCellIndex key] {
            get => base[key];
            set => base[key] = (IDFR_BattleCellModelTD)value;
        }
        IDFR_BattleCellModelBase IDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.this[DFR_BattleCellIndex key] {
            get => base[key];
            set => base[key] = (IDFR_BattleCellModelTD)value;
        }

        private event IDictionaryDataUpdated<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.UpdatedDelegate m_Updated;
        event IDictionaryDataUpdated<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.UpdatedDelegate IDictionaryDataUpdated<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Updated {
            add => m_Updated += value;
            remove => m_Updated -= value;
        }

        private event IDictionaryDataAdded<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.AddedDelegate m_Added;
        event IDictionaryDataAdded<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.AddedDelegate IDictionaryDataAdded<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Added {
            add => m_Added += value;
            remove => m_Added -= value;
        }

        private event IDictionaryDataRemoved<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.RemovedDelegate m_Removed;
        event IDictionaryDataRemoved<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.RemovedDelegate IDictionaryDataRemoved<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Removed {
            add => m_Removed += value;
            remove => m_Removed -= value;
        }

        private event IDictionaryDataCleared<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.ClearedDelegate m_Cleared;
        event IDictionaryDataCleared<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.ClearedDelegate IDictionaryDataCleared<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Cleared {
            add => m_Cleared += value;
            remove => m_Cleared -= value;
        }

        IEnumerator<KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase>> IEnumerable<KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase>>.GetEnumerator() {
            foreach (var key in Keys) {
                yield return KeyValuePair.Create(key, (IDFR_BattleCellModelBase)this[key]);
            }
        }

        IDFR_BattleCellModelBase IReadOnlyDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.GetValue(DFR_BattleCellIndex key) => GetValue(key);

        bool IReadOnlyDictionary<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.TryGetValue(DFR_BattleCellIndex key, out IDFR_BattleCellModelBase value) {
            if (TryGetValue(key, out var result)) {
                value = result;
                return true;
            }
            value = default;
            return false;
        }

        bool IDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.TryAdd(DFR_BattleCellIndex key, IDFR_BattleCellModelBase value) => TryAdd(key, (IDFR_BattleCellModelTD)value);

        bool IDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.TryAdd(KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase> item) => TryAdd(KeyValuePair.Create(item.Key, (IDFR_BattleCellModelTD)item.Value));

        bool IDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.TryGetValue(DFR_BattleCellIndex key, out IDFR_BattleCellModelBase value) {
            if (TryGetValue(key, out var result)) {
                value = result;
                return true;
            }
            value = default;
            return false;
        }

        void IFixedLengthDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Update(DFR_BattleCellIndex key, IDFR_BattleCellModelBase value) => Update(key, (IDFR_BattleCellModelTD)value);

        void IFixedLengthDictionaryData<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Update(DFR_BattleCellIndex key, Action<IDFR_BattleCellModelBase> updater) => Update(key, updater);

        void IDictionary<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.Add(DFR_BattleCellIndex key, IDFR_BattleCellModelBase value) => Add(key, (IDFR_BattleCellModelTD)value);

        bool IDictionary<DFR_BattleCellIndex, IDFR_BattleCellModelBase>.TryGetValue(DFR_BattleCellIndex key, out IDFR_BattleCellModelBase value) {
            if (TryGetValue(key, out var result)) {
                value = result;
                return true;
            }
            value = default;
            return false;
        }

        void ICollection<KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase>>.Add(KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase> item) => Add(KeyValuePair.Create(item.Key, (IDFR_BattleCellModelTD)item.Value));

        bool ICollection<KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase>>.Contains(KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase> item) => Contains(KeyValuePair.Create(item.Key, (IDFR_BattleCellModelTD)item.Value));

        void ICollection<KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase>>.CopyTo(KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase>[] array, int arrayIndex) {
            foreach (var key in Keys) {
                array[arrayIndex++] = KeyValuePair.Create(key, (IDFR_BattleCellModelBase)this[key]);
            }
        }

        bool ICollection<KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase>>.Remove(KeyValuePair<DFR_BattleCellIndex, IDFR_BattleCellModelBase> item) => Remove(KeyValuePair.Create(item.Key, (IDFR_BattleCellModelTD)item.Value));
    }
}
